package es.us.idinfor;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class Window {
	private String id;
	private long timeStampStart;
	private long timeStampEnd;
	private List<Event> events;
	private Map<String, Integer> occurrences;
	
	public Window(String name, long milisecondsStart, long milisecondsEnd) {
		id = name;
		timeStampStart = milisecondsStart;
		timeStampEnd = milisecondsEnd;
		events = Lists.newArrayList();
		occurrences = Maps.newHashMap();
	}
	
	public String getId() {
		return id;
	}
	
	public long getTimeStampStart() {
		return timeStampStart;
	}
	
	public long getTimeStampEnd() {
		return timeStampEnd;
	}
	
	public List<Event> getEvents() {
		return events;
	}
	
	public boolean add(Event e) {
		boolean res = false;
		Integer aux = 0;
		
		if(((getTimeStampStart() - e.getTimeStamp()) <= 0) && ((e.getTimeStamp() - getTimeStampEnd()) < 0)) {
			res = getEvents().add(e);
			
			if(res) {
				Collections.sort(getEvents());
				
				aux = occurrences.get(e.getId());
				
				if(aux == null) {
					occurrences.put(e.getId(), 1);
				}
				else {
					occurrences.put(e.getId(), aux + 1);
				}
			}
		}
		
		return res;
	}
	
	public boolean isEmpty() {
		return getEvents().isEmpty();
	}
	
	public Date width() {
		return new Date(getTimeStampEnd() - getTimeStampStart());
	}
	
	public int size() {
		return events.size();
	}
	
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		
		for(Entry<String, Integer> e: occurrences.entrySet()) {
			result = prime * result + ((e.getKey() == null)? 0 : e.getKey().hashCode());
			result = prime * result + ((e.getValue() == null)? 0 : e.getValue().hashCode());
		}
		
		return result;
	}

	public boolean equals(Object obj) {
		if(this == obj) {
			return true;
		}
		
		if(obj == null) {
			return false;
		}
		
		if(getClass() != obj.getClass()) {
			return false;
		}
		
		Window other = (Window) obj;
		
		if(occurrences == null) {
			if(other.occurrences != null) {
				return false;
			}
		}
		else {
			Integer aux = null;
			
			for(Entry<String, Integer> e: occurrences.entrySet()) {
				aux = other.occurrences.get(e.getKey());
				
				if((aux == null) || !aux.equals(e.getValue())) {
					return false;
				}
			}
			
			aux = null;
		}
		
		return true;
	}

	public String toString() {
		String res = getId() + " = {";
		
		for(Event e: getEvents()) {
			res += e.toString() + ", ";
		}
		
		if(!isEmpty()) {
			res = res.substring(0, res.length() - 2);
		}
		
		res += "}";
		
		return res;
	}
}
